package nmp.lib;

import java.util.ArrayList;
import java.util.Iterator;

import nmp.remote.R;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Handler;
import android.util.Log;


public class CNmpDevice {
	
	private enum CONTROL_STATE {
		NONE,
		SCAN_DEVICE,
		CONNECTING,
		READY
	};
	
	
	protected static final String STR_SYNC_C = "NMPALIVE_C";
	protected static final String STR_SYNC_S = "NMPALIVE_S";
	
	public static final int DEVICE_STATUS_DISCONNECT = 0;
	public static final int DEVICE_STATUS_CONNECT = 1;
	
	private ArrayList<CNmpDeviceItem> mDeviceList = null;
	private Context mContext = null;
	private ProgressDialog mScanBusyDialog = null;
	private ProgressDialog mConnectBusyDialog = null;
	private int mMsgPort = 0;
	
	private Handler mHandlerTime;
    private Runnable mTimerRun;
    private CONTROL_STATE mState;
    private int mRetryDruation;
    private CNmpWifiManage mWifi;
    private String mLastConnectedSSID;
    private String mRetryConnectedSSID;
    private boolean mRetryConnect = false;
    
	CNmpUdp m_scan_client = null;
	CNmpTcp m_msg_client = null;

	int m_scan_port = 0;
	int m_current_status = DEVICE_STATUS_DISCONNECT;

	public class CNmpDeviceItem
	{
		public String name;
		public String address;
		public int port;
		
		public CNmpDeviceItem(String name,String address,int port) {
			this.name = name;
			this.address = address;
			this.port = port;
		}
	};
	
	public CNmpDevice(Context context,int port) {
		mContext = context;
		mMsgPort = port;
		mState = CONTROL_STATE.NONE;
		mRetryConnect = false;
		
		
		mScanBusyDialog = new ProgressDialog(mContext);  
		mScanBusyDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
		mScanBusyDialog.setTitle(mContext.getString(R.string.search_dongle_device)); 
		mScanBusyDialog.setIndeterminate(false);
		mScanBusyDialog.setCancelable(true);
		mScanBusyDialog.setButton(ProgressDialog.BUTTON_NEUTRAL,"Cancel",new DialogInterface.OnClickListener(){  
			  
            public void onClick(DialogInterface dialog, int which) {  
                dialog.cancel();  
            } 
        });		
		
		mConnectBusyDialog = new ProgressDialog(mContext);  
		mConnectBusyDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
		mConnectBusyDialog.setTitle(mContext.getString(R.string.connect_to_dongle_device));
		mConnectBusyDialog.setIndeterminate(false);
		mConnectBusyDialog.setCancelable(true);
		mConnectBusyDialog.setButton(ProgressDialog.BUTTON_NEUTRAL,"Cancel",new DialogInterface.OnClickListener(){  			  
            public void onClick(DialogInterface dialog, int which) {  
            	CloseConnectCmdDelay();            	
            	mState = CONTROL_STATE.NONE;
            	mScanBusyDialog.dismiss();
            	DeviceStatus(DEVICE_STATUS_DISCONNECT);
                dialog.cancel();  
            } 
        });		
		mWifi = new CNmpWifiManage(mContext);
	}

	public void ScanFinish(ArrayList<CNmpDeviceItem> target_list){
		
	}
	
	public boolean Scan(){
		
		if(mDeviceList == null)
			mDeviceList = new ArrayList<CNmpDeviceItem>();
		m_scan_port = mMsgPort + 1;
		mDeviceList.clear();
		

		if(!mWifi.IsConnected()){	
        	Log.e(this.toString(),"WifiInital error!");				
			return false;			
		}

								
		m_scan_client = new CNmpUdp(){
			public void GetString(String str, String from, int port) {
				Log.e(this.toString(),"Get message "+str+" from "+from+" port:" + port);
				CNmpDeviceItem item = null;
				String[] str_array = str.split(":");
				
				if(str_array != null){
					for(String tmp_str:str_array){
						Log.e(this.toString(),"string arrar:" + tmp_str);
					}					
				}

				if(str_array == null){
					if(str.equals(STR_SYNC_S)){
						item = new CNmpDeviceItem("NMP Device",from,port);
						mDeviceList.add(item);
					}
				} else {
					if(str_array[0].equals(STR_SYNC_S)) {
						if(str_array.length>1) {
							item = new CNmpDeviceItem(str_array[1],from,port);
						} else {
							item = new CNmpDeviceItem("NMP Device",from,port);
						}
						mDeviceList.add(item);	
					}	
				}
				
			}
		

			public void UpdateStatus(int status) {
		    	switch(status) {
		    	
		    		case MSG_TIMEOUT:
		    			//m_target_list.add(mContext.getString(R.string.str_devlist_broadcast));					
						//mDeviceList.add(m_broadcase_addr.getHostAddress());
						//mDeviceList.add(mContext.getString(R.string.customize));
						ScanFinshHandle(mDeviceList);		    			
		    			break;
		    			
		    		case MSG_READY:
		    			ScanStart(m_scan_port);
		    			break;
		    	}
		    }			
		};
		m_scan_client.setTimeout(3000,true);
		m_scan_client.start();			
		return true; 
	}
	
	public boolean Connect(int duration,String ssid) {
		mRetryDruation = duration;
		boolean ret;
		if(mRetryDruation != 0) {
			mRetryConnect = true;
			mRetryConnectedSSID = ssid;
			mConnectBusyDialog.show(); 
			if(!DeviceConnect(ssid)) {
				CheckIsConnectCmdDelay(mRetryDruation);
			}
			return true;
		} else {
			mRetryConnect = false;
			ret = DeviceConnect(ssid);
			if(!ret) {
				mConnectBusyDialog.dismiss();
			}
			return ret;
		}
	}
	
	public boolean Connect(){
		return Connect(0,null);
	}
	
	public boolean ReConnect(int duration){
		return Connect(duration,mLastConnectedSSID);
	}	
	
	public void GetMessage(String str) {

	}
	
	public void SendMessage(String message) {
		 
		if(m_current_status == DEVICE_STATUS_CONNECT) {
			Log.e(this.toString(),"Send message: " + message); 
			m_msg_client.SendString(message);		
		} else {
			Log.e(this.toString(),"m_current_status is not ready,skip message: " + message);	
		}
	}
	
	public void DeviceStatus(int status){
		switch(status) {
			case DEVICE_STATUS_DISCONNECT:
				break;
			case DEVICE_STATUS_CONNECT:
				break;
		}
	}
	
	public void Disconnect(){
		mState = CONTROL_STATE.NONE;
		CloseConnectCmdDelay();   
		if(m_msg_client != null)
		{	
			m_msg_client.close();
			m_msg_client = null;
		}
		m_current_status = -1;
	}
	
	public String GetCurrentWifiSSid() {
		if(mWifi.IsConnected()) {
			return mWifi.GetWifiSSID();
		} else {
			return null;
		}
	}
	
	private void ScanFinshHandle(ArrayList<CNmpDeviceItem> target_list) {
		ScanFinish(target_list);
		mScanBusyDialog.dismiss();	
		Log.e(this.toString(),"m_scan_client get:" + target_list.size());		
		if(m_scan_client != null){
			m_scan_client.close();
			m_scan_client = null;
		}
	}
	
	private void ScanStart(int port){
		if(m_scan_client != null)
		{
			m_scan_client.SendString(STR_SYNC_C,mWifi.GetBroadcastAddress(), port);
			mScanBusyDialog.show();  		
		}
	}
	
	private void CloseConnectCmdDelay() {
		
		if(mHandlerTime != null) {
			mHandlerTime.removeCallbacks(mTimerRun);
			mTimerRun = null;
			mHandlerTime = null;
		} 		
	}	
		
	private void CheckIsConnectCmdDelay(int duration) {
		Log.e(this.toString(),"!!!!!!!!CheckIsConnectCmdDelay!!!!!!!!!!");
		mHandlerTime = new Handler();		
		mTimerRun = new Runnable(){
		    public void run() {			    			    	
		    	DeviceConnect(mRetryConnectedSSID);	    	
		    }
		};			  
		mConnectBusyDialog.show(); 
		mHandlerTime.postDelayed(mTimerRun, duration);
	}
	
	private boolean DeviceConnect(String ssid){

		if(m_msg_client != null) {
			Disconnect();
		}

		if(!mWifi.IsConnected(ssid)){
			if(m_msg_client != null)
				m_msg_client.close();				
			return false;
		}
		
		m_msg_client = new CNmpTcp(false,mWifi.GetGatewayAddress(),mMsgPort){
			
			public void GetString(String str, String from, int port){
				Log.e(this.toString(),"Get string:" + str + "from: " + from + ":" + port);
				GetMessage(str);
			}
			
			public void UpdateStatus(int status, String address, int port) {
	
				if(m_current_status == status)
					return;				
				m_current_status = status;
				
				switch(status){
					case MSG_NET_STATUS_CONNECT:	
						mState = CONTROL_STATE.READY;
						mConnectBusyDialog.dismiss(); 
						mLastConnectedSSID = mWifi.GetWifiSSID();
						Log.e(this.toString(),"Connected:" + "from: " + address + ":" + port); 
						DeviceStatus(DEVICE_STATUS_CONNECT);
						break;
					default:	
							
						if(mRetryConnect) {
							Log.e(this.toString(),"Disconnect !, retry again after duration: " + mRetryDruation 
									+ "  from: " + address + ":" + port);									
							mState = CONTROL_STATE.CONNECTING;
							CheckIsConnectCmdDelay(mRetryDruation);
						} else {
							Log.e(this.toString(),"Disconnect ! " +" from: " + address + ":" + port);								
							mState = CONTROL_STATE.NONE;
							DeviceStatus(DEVICE_STATUS_DISCONNECT);		
						}
						break;					
				}
			}
		};	
		
		m_msg_client.setTimeout(0,5000, true);
		
		m_msg_client.start();
		
		return true;
	}

	static public boolean SearchNmpDevice(String device_address,ArrayList<String> m_target_list){
		boolean isMatch = false;
		String device = null;
		
		Iterator<String> iterator = m_target_list.iterator();
		
        while(iterator.hasNext()) {
        	device = (String) iterator.next();
        	if(device.equals(device_address)){
        		isMatch = true;
        		break;
        	}
        }
				
		return isMatch;
	}

}
